// Fill out your copyright notice in the Description page of Project Settings.


#include "Character/BaseCharacter.h"

#include "AbilitySystemComponent.h"
#include "AbilitySystem/AuraAbilitySystemComponent.h"
#include "Components/CapsuleComponent.h"
#include "Game/AuraGameplayTags.h"
#include "Kismet/GameplayStatics.h"

ABaseCharacter::ABaseCharacter()
{
	Weapon = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Weapon"));
	Weapon->SetupAttachment(GetMesh(), "WeaponHandSocket");
	Weapon->SetCollisionEnabled(ECollisionEnabled::NoCollision);

	//设置碰撞体可以生成重叠事件
	GetCapsuleComponent()->SetGenerateOverlapEvents(true);
}

UAbilitySystemComponent* ABaseCharacter::GetAbilitySystemComponent() const
{
	return AbilitySystemComponent;
}


void ABaseCharacter::BeginPlay()
{
	Super::BeginPlay();
}

void ABaseCharacter::InitDefaultAttributes() const
{
	check(IsValid(GetAbilitySystemComponent()));
	check(DefaultPrimaryAttributeEffectClass)
	check(DefaultSecondaryAttributeEffectClass)
	check(DefaultVitalAttributeEffectClass)

	FGameplayEffectContextHandle GEContextHandle = AbilitySystemComponent->MakeEffectContext();
	GEContextHandle.AddSourceObject(this);
	const FGameplayEffectSpecHandle PrimaryGESpecHandle = AbilitySystemComponent->MakeOutgoingSpec(
		DefaultPrimaryAttributeEffectClass,
		1.f,
		GEContextHandle
	);
	const FGameplayEffectSpecHandle SecondaryGESpecHandle = AbilitySystemComponent->MakeOutgoingSpec(
		DefaultSecondaryAttributeEffectClass,
		1.f,
		GEContextHandle
	);
	FGameplayEffectSpecHandle VitalGESpecHandle = AbilitySystemComponent->MakeOutgoingSpec(
		DefaultVitalAttributeEffectClass,
		1.f,
		GEContextHandle
	);

	/** 应用初始化属性GE */
	AbilitySystemComponent->ApplyGameplayEffectSpecToSelf(*PrimaryGESpecHandle.Data.Get());
	AbilitySystemComponent->ApplyGameplayEffectSpecToSelf(*SecondaryGESpecHandle.Data.Get());
	AbilitySystemComponent->ApplyGameplayEffectSpecToSelf(*VitalGESpecHandle.Data.Get());
}




UAttributeSet* ABaseCharacter::GetAttributeSet() const
{
	return AttributeSet;
}

FVector ABaseCharacter::GetCombatSocketLocation_Implementation() const
{
	return Weapon->GetSocketLocation(WeaponTipSocketName);
}

UAnimMontage* ABaseCharacter::GetHitReactMontage_Implementation() const
{
	return HitReactMontage;
}

AActor* ABaseCharacter::GetAvatar_Implementation()
{
	return this;
}

bool ABaseCharacter::IsDead_Implementation() const
{
	return bDead;
}

void ABaseCharacter::Dissolve()
{
	TArray<UMaterialInstanceDynamic*> MaterialInstDynamics;
	// 设置角色网格溶解
	if (IsValid(DissolveMaterialInstance))
	{
		// 创建溶解动态材质实例
		UMaterialInstanceDynamic* MaterialInstanceDynamic = UMaterialInstanceDynamic::Create(
			DissolveMaterialInstance,
			this
		);
		// 将动态材质实例应用到角色的网格上
		GetMesh()->SetMaterial(0, MaterialInstanceDynamic);
		MaterialInstDynamics.Add(MaterialInstanceDynamic);
	}

	if (IsValid(WeaponDissolveMaterialInstance))
	{
		UMaterialInstanceDynamic* MaterialInstanceDynamic = UMaterialInstanceDynamic::Create(
			WeaponDissolveMaterialInstance,
			this
		);
		// 将动态材质实例应用到武器网格上
		Weapon->SetMaterial(0, MaterialInstanceDynamic);
		MaterialInstDynamics.Add(MaterialInstanceDynamic);
	}

	// 开始溶解效果
	StartDissolveTimeline(MaterialInstDynamics);
}

void ABaseCharacter::Die()
{
	//将武器从角色身上分离
	Weapon->DetachFromComponent(FDetachmentTransformRules(EDetachmentRule::KeepWorld, true));

	// 网络广播死亡
	MulticastHandleDeath();
}

TArray<FTaggedMontage> ABaseCharacter::GetAttackMontages_Implementation() const
{
	return AttackMontages;
}

FVector ABaseCharacter::GetCombatSocketLocationByStruct_Implementation(const FTaggedMontage& TaggedMontage) const
{
	if (TaggedMontage.MontageTag.MatchesTagExact(FAuraGameplayTags::Get().CombatSocket_Weapon))
	{
		return Weapon->GetSocketLocation(TaggedMontage.CombatTipSocketName);
	}

	return GetMesh()->GetSocketLocation(TaggedMontage.CombatTipSocketName);
}

UNiagaraSystem* ABaseCharacter::GetBloodEffect_Implementation() const
{
	return BloodEffect;
}

FTaggedMontage ABaseCharacter::GetTaggedMontageByTag_Implementation(const FGameplayTag& MontageTag) const
{
	for (const FTaggedMontage& Montage : AttackMontages)
	{
		if (Montage.MontageTag.MatchesTagExact(MontageTag))
		{
			return Montage;
		}
	}

	UE_LOG(LogTemp, Warning, TEXT(" 未找到对应montage "));
	return FTaggedMontage();
}

FVector ABaseCharacter::GetCombatSocketLocationByTag_Implementation(
	const FGameplayTag SocketTag, const FName& SocketName
) const
{
	if (SocketTag.MatchesTagExact(FAuraGameplayTags::Get().CombatSocket_Weapon))
	{
		return Weapon->GetSocketLocation(SocketName);
	}

	return GetMesh()->GetSocketLocation(SocketName);
}

int32 ABaseCharacter::GetMinionsCount_Implementation()
{
	return MinionsCount;
}

void ABaseCharacter::IncrementMinionsCount_Implementation(const int32 Amount)
{
	MinionsCount += Amount;
}

ERoleClass ABaseCharacter::GetRoleClass_Implementation() const
{
	return RoleClass;
}

int32 ABaseCharacter::GetLevel()
{
	return Level;
}

void ABaseCharacter::MulticastHandleDeath_Implementation()
{
	// 播放死亡音效
	UGameplayStatics::PlaySoundAtLocation(this, DeathSound, GetActorLocation());
	
	//开启武器物理效果
	Weapon->SetSimulatePhysics(true);
	//开启重力效果
	Weapon->SetEnableGravity(true);
	//开启物理碰撞
	Weapon->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);

	//开启角色模拟物理效果
	GetMesh()->SetSimulatePhysics(true);
	//开启重力效果
	GetMesh()->SetEnableGravity(true);
	//开启物理碰撞
	GetMesh()->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);
	//开启角色与静态物体产生碰撞
	GetMesh()->SetCollisionResponseToChannel(ECC_WorldStatic, ECollisionResponse::ECR_Block);

	//关闭胶囊碰撞，避免其对武器和角色模拟物理效果产生影响
	GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);

	// 触发溶解效果
	Dissolve();

	// 设置状态为死亡
	bDead = true;
}
